﻿using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OpenXmlTools.OpenXML.Word
{
    /// <summary>
    /// Word表格帮助类
    /// </summary>
    public static class WordTableHelper
    {
        /// <summary>
        /// 填充Word文档中的表格数据
        /// </summary>
        /// <param name="fileStream">Word文档流</param>
        /// <param name="tablesData">表格数据字典（表格索引或标识符 -> 行数据）</param>
        /// <param name="identifierType">标识类型</param>
        /// <param name="tableDataStartRowIndex">表格数据起始行索引（行索引从0开始，默认为1，表示表格第一行为表头，数据从第二行开始）</param>
        /// <param name="useDefaultFormat">是否使用默认格式（边框：单实线，0.5磅，黑色；字体：宋体(中文)，Arial(ASCII字符字体)；内容居中对齐）</param>
        public static MemoryStream FillTables(Stream fileStream, Dictionary<string, List<List<string>>> tablesData, WordTableIdentifierType identifierType = WordTableIdentifierType.None, int tableDataStartRowIndex = 1, bool useDefaultFormat = true)
        {
            // 创建文档的可写副本
            using var memoryStream = new MemoryStream();
            fileStream.CopyTo(memoryStream);
            memoryStream.Position = 0;
            fileStream.Position = 0;

            // 打开Word文档
            using (WordprocessingDocument doc = WordprocessingDocument.Open(memoryStream, true))
            {
                // 获取主文档部分
                MainDocumentPart? mainPart = doc.MainDocumentPart;
                if (mainPart != null)
                {
                    // 获取所有表格
                    var tables = mainPart.Document.Descendants<Table>().ToList();

                    foreach (var kvp in tablesData)
                    {
                        string tableIdentifier = kvp.Key;
                        List<List<string>> tableData = kvp.Value;

                        // 查找目标表格
                        Table? targetTable = FindTable(tables, tableIdentifier, identifierType);

                        if (targetTable != null)
                        {
                            FillTableData(targetTable, tableData, tableDataStartRowIndex, useDefaultFormat);
                        }
                    }

                    // 保存文档
                    mainPart.Document.Save();
                }
            }

            // 重置流的读取/写入位置到起始点
            memoryStream.Position = 0;

            return memoryStream;
        }

        /// <summary>
        /// 填充Word文档中的表格数据
        /// </summary>
        /// <param name="mainPart">主文档部分</param>
        /// <param name="tablesData">表格数据字典（表格索引或标识符 -> 行数据）</param>
        /// <param name="identifierType">标识类型</param>
        /// <param name="tableDataStartRowIndex">表格数据起始行索引</param>
        /// <param name="useDefaultFormat">是否使用默认格式（边框：单实线，0.5磅，黑色；字体：宋体(中文)，Arial(ASCII字符字体)；内容居中对齐）</param>
        public static void FillTables(MainDocumentPart mainPart, Dictionary<string, List<List<string>>> tablesData, WordTableIdentifierType identifierType, int tableDataStartRowIndex, bool useDefaultFormat)
        {
            // 获取所有表格
            var tables = mainPart.Document.Descendants<Table>().ToList();

            foreach (var kvp in tablesData)
            {
                string tableIdentifier = kvp.Key;
                List<List<string>> tableData = kvp.Value;

                // 查找目标表格
                Table? targetTable = FindTable(tables, tableIdentifier, identifierType);

                if (targetTable != null)
                {
                    FillTableData(targetTable, tableData, tableDataStartRowIndex, useDefaultFormat);
                }
            }
        }

        /// <summary>
        /// 填充Word文档中的表格数据，同时合并单元格
        /// </summary>
        /// <param name="fileStream">Word文档流</param>
        /// <param name="wordTables">表格数据集合</param>
        /// <param name="identifierType">标识类型</param>
        /// <param name="tableDataStartRowIndex">表格数据起始行索引（行索引从0开始，默认为1，表示表格第一行为表头，数据从第二行开始）</param>
        /// <param name="useDefaultFormat">是否使用默认格式（边框：单实线，0.5磅，黑色；字体：宋体(中文)，Arial(ASCII字符字体)；内容居中对齐）</param>
        public static MemoryStream FillTables(Stream fileStream, List<WordTable> wordTables, WordTableIdentifierType identifierType = WordTableIdentifierType.None, int tableDataStartRowIndex = 1, bool useDefaultFormat = true)
        {
            // 创建文档的可写副本
            using var memoryStream = new MemoryStream();
            fileStream.CopyTo(memoryStream);
            memoryStream.Position = 0;
            fileStream.Position = 0;

            // 打开Word文档
            using (WordprocessingDocument doc = WordprocessingDocument.Open(memoryStream, true))
            {
                // 获取主文档部分
                MainDocumentPart? mainPart = doc.MainDocumentPart;
                if (mainPart != null)
                {
                    // 获取所有表格
                    var tables = mainPart.Document.Descendants<Table>().ToList();

                    foreach (var wt in wordTables)
                    {
                        string tableIdentifier = wt.TableIdentifier;
                        List<List<string>> tableData = wt.TableDatas;

                        // 查找目标表格
                        Table? targetTable = FindTable(tables, tableIdentifier, identifierType);

                        if (targetTable != null)
                        {
                            //填充表格数据
                            FillTableData(targetTable, tableData, tableDataStartRowIndex, useDefaultFormat);

                            if (wt.MergeRegions.Count > 0)
                            {
                                //合并单元格
                                WordTableMergeHelper.BatchMergeCells(targetTable, wt.MergeRegions);
                            }
                        }
                    }

                    // 保存文档
                    mainPart.Document.Save();
                }
            }

            // 重置流的读取/写入位置到起始点
            memoryStream.Position = 0;

            return memoryStream;
        }

        /// <summary>
        /// 填充Word文档中的表格数据，同时合并单元格
        /// </summary>
        /// <param name="doc">Word文档</param>
        /// <param name="wordTables">表格数据集合</param>
        /// <param name="identifierType">标识类型</param>
        /// <param name="tableDataStartRowIndex">表格数据起始行索引（行索引从0开始，默认为1，表示表格第一行为表头，数据从第二行开始）</param>
        /// <param name="useDefaultFormat">是否使用默认格式（边框：单实线，0.5磅，黑色；字体：宋体(中文)，Arial(ASCII字符字体)；内容居中对齐）</param>
        public static void FillTables(WordprocessingDocument doc, List<WordTable> wordTables, WordTableIdentifierType identifierType = WordTableIdentifierType.None, int tableDataStartRowIndex = 1, bool useDefaultFormat = true)
        {
            // 获取主文档部分
            MainDocumentPart? mainPart = doc.MainDocumentPart;
            if (mainPart != null)
            {
                // 获取所有表格
                var tables = mainPart.Document.Descendants<Table>().ToList();

                foreach (var wt in wordTables)
                {
                    string tableIdentifier = wt.TableIdentifier;
                    List<List<string>> tableData = wt.TableDatas;

                    // 查找目标表格
                    Table? targetTable = FindTable(tables, tableIdentifier, identifierType);

                    if (targetTable != null)
                    {
                        //填充表格数据
                        FillTableData(targetTable, tableData, tableDataStartRowIndex, useDefaultFormat);

                        if (wt.MergeRegions.Count > 0)
                        {
                            //合并单元格
                            WordTableMergeHelper.BatchMergeCells(targetTable, wt.MergeRegions);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 根据标识符查找表格
        /// </summary>
        /// <param name="tables">Word文档中的所有表格</param>
        /// <param name="identifier">标识</param>
        /// <param name="identifierType">标识类型</param>
        /// <returns>目标表格</returns>
        public static Table? FindTable(List<Table> tables, string identifier, WordTableIdentifierType identifierType = WordTableIdentifierType.None)
        {
            Table? table = null;

            switch (identifierType)
            {
                case WordTableIdentifierType.Index:
                    // 尝试按索引查找
                    if (int.TryParse(identifier, out int index))
                    {
                        if (index >= 0 && index < tables.Count)
                        {
                            table = tables[index];
                        }
                    }
                    break;
                case WordTableIdentifierType.Bookmark:
                    // 尝试按书签查找
                    table = FindTableRecursiveByBookmark(tables, identifier);
                    break;
                case WordTableIdentifierType.Title:
                    // 尝试按标题文本查找
                    table = FindTableByTitle(tables, identifier);
                    break;
                default:
                    table = FindTable(tables, identifier);
                    break;
            }

            return table;
        }

        /// <summary>
        /// 根据标识符查找表格
        /// </summary>
        /// <param name="tables">Word文档中的所有表格</param>
        /// <param name="identifier">标识</param> 
        /// <returns>目标表格</returns>
        public static Table? FindTable(List<Table> tables, string identifier)
        {
            // 尝试按索引查找
            if (int.TryParse(identifier, out int index))
            {
                if (index >= 0 && index < tables.Count)
                {
                    return tables[index];
                }
            }

            // 尝试按书签查找
            Table? bookmarkedTable = FindTableRecursiveByBookmark(tables, identifier);
            if (bookmarkedTable != null)
            {
                return bookmarkedTable;
            }

            // 尝试按标题文本查找
            return FindTableByTitle(tables, identifier);
        }

        /// <summary>
        /// 通过书签查找表格
        /// </summary>
        /// <param name="tables">Word文档中的所有表格</param>
        /// <param name="bookmarkName">书签名称</param>
        /// <returns>目标表格</returns>
        public static Table? FindTableByBookmark(List<Table> tables, string bookmarkName)
        {
            foreach (var table in tables)
            {
                // 查找表格前的书签
                var prevSibling = table.PreviousSibling();
                while (prevSibling != null)
                {
                    if (prevSibling is BookmarkStart bookmark && bookmark.Name == bookmarkName)
                    {
                        return table;
                    }
                    prevSibling = prevSibling.PreviousSibling();
                }

                // 查找表格中的书签
                var bookmarkStart = table.Descendants<BookmarkStart>().FirstOrDefault(bs => bs.Name == bookmarkName);
                if (bookmarkStart != null)
                {
                    return table;
                }
            }

            return null;
        }

        /// <summary>
        /// 通过书签查找表格（支持嵌套表格）
        /// </summary>
        /// <param name="allTables">Word文档中的所有表格</param>
        /// <param name="bookmarkName">书签名称</param>
        /// <returns>目标表格</returns>
        public static Table? FindTableRecursiveByBookmark(List<Table> allTables, string bookmarkName)
        {
            // 第一轮：快速查找 - 直接匹配表头书签
            var fastTable = FindByHeaderBookmark(allTables, bookmarkName);
            if (fastTable != null)
            {
                return fastTable;
            }

            // 第二轮：深度查找 - 搜索表格内书签
            foreach (var table in allTables)
            {
                var foundTable = SearchTableRecursive(table, bookmarkName, allTables);
                if (foundTable != null)
                {
                    return foundTable;
                }
            }

            return null;
        }

        /// <summary>
        /// 查找表格头部书签
        /// </summary>
        /// <param name="tables">Word文档中的所有表格</param>
        /// <param name="bookmarkName">书签名称</param>
        /// <returns>目标表格</returns>
        public static Table? FindByHeaderBookmark(List<Table> tables, string bookmarkName)
        {
            foreach (var table in tables)
            {
                // 查找表格前的书签（表头书签）
                var prevSibling = table.PreviousSibling();
                while (prevSibling != null)
                {
                    if (prevSibling is BookmarkStart bookmark && bookmark.Name == bookmarkName)
                    {
                        return table;
                    }
                    prevSibling = prevSibling.PreviousSibling();
                }
            }
            return null;
        }

        /// <summary>
        /// 递归搜索表格及其单元格内的书签
        /// </summary>
        /// <param name="element">文档元素</param>
        /// <param name="bookmarkName">书签名称</param>
        /// <param name="allTables">Word文档中的所有表格</param>
        /// <returns>目标表格</returns>
        public static Table? SearchTableRecursive(OpenXmlElement element, string bookmarkName, List<Table> allTables)
        {
            // 检查当前元素是否为书签
            if (element is BookmarkStart bookmarkStart && bookmarkStart.Name == bookmarkName)
            {
                // 查找最近的父级表格
                return FindNearestParentTable(bookmarkStart, allTables);
            }

            // 如果是表格单元格，递归搜索其内容
            if (element is TableCell cell)
            {
                foreach (var child in cell.ChildElements)
                {
                    var result = SearchTableRecursive(child, bookmarkName, allTables);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }

            // 如果是表格，递归搜索其行
            if (element is TableRow row)
            {
                foreach (var cellInRow in row.Elements<TableCell>())
                {
                    var result = SearchTableRecursive(cellInRow, bookmarkName, allTables);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }

            // 如果是表格或容器元素，递归搜索其子元素
            if (element.HasChildren)
            {
                foreach (var child in element.ChildElements)
                {
                    var result = SearchTableRecursive(child, bookmarkName, allTables);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 为书签查找最近的父级表格
        /// </summary>
        /// <param name="element">书签元素</param>
        /// <param name="allTables">Word文档中的所有表格</param>
        /// <returns>最近的父级表格</returns>
        public static Table? FindNearestParentTable(OpenXmlElement element, List<Table> allTables)
        {
            var ancestor = element.Parent;
            while (ancestor != null)
            {
                if (ancestor is Table table)
                {
                    // 验证表格是否在有效集合中（避免返回嵌套表格的副本）
                    return allTables.Contains(table) ? table : null;
                }
                ancestor = ancestor.Parent;
            }
            return null;
        }

        /// <summary>
        /// 通过标题文本查找表格
        /// </summary>
        /// <param name="tables">Word文档中的所有表格</param>
        /// <param name="titleText">标题文本</param>
        /// <returns>目标表格</returns>
        public static Table? FindTableByTitle(List<Table> tables, string titleText)
        {
            foreach (var table in tables)
            {
                // 查找表格前的段落作为标题
                var prevSibling = table.PreviousSibling();
                while (prevSibling != null)
                {
                    if (prevSibling is Paragraph paragraph)
                    {
                        string text = GetParagraphText(paragraph);
                        if (text.Contains(titleText))
                        {
                            return table;
                        }
                    }
                    prevSibling = prevSibling.PreviousSibling();
                }
            }

            return null;
        }

        /// <summary>
        /// 获取段落文本
        /// </summary>
        public static string GetParagraphText(Paragraph paragraph)
        {
            return string.Join("", paragraph.Descendants<Text>().Select(t => t.Text));
        }

        /// <summary>
        /// 填充表格数据
        /// </summary>
        /// <param name="table">待填充的表格</param>
        /// <param name="data">填充的数据</param>
        /// <param name="tableDataStartRowIndex">表格数据起始行索引（行索引从0开始，默认为1，表示表格第一行为表头，数据从第二行开始）</param>
        /// <param name="useDefaultFormat">是否使用默认格式（边框：单实线，0.5磅，黑色；字体：宋体(中文)，Arial(ASCII字符字体)；内容居中对齐）</param>
        public static void FillTableData(Table table, List<List<string>> data, int tableDataStartRowIndex = 1, bool useDefaultFormat = true)
        {
            //先删除原有的数据行
            var rowsToDelete = table.Elements<TableRow>().Skip(tableDataStartRowIndex).ToList();
            foreach (var row in rowsToDelete)
            {
                row.Remove();
            }

            // 获取现有行和列信息
            var rows = table.Elements<TableRow>().ToList();
            int rowCount = rows.Count;
            int columnCount = rows.Count > 0 ? rows[0].Elements<TableCell>().Count() : 0;

            // 确保有足够的行
            while (rows.Count - tableDataStartRowIndex < data.Count)
            {
                var newRow = new TableRow();
                for (int i = 0; i < columnCount; i++)
                {
                    newRow.AppendChild(new TableCell(new Paragraph(new Run(new Text()))));
                }
                table.AppendChild(newRow);
                rows = table.Elements<TableRow>().ToList();
            }

            // 填充数据
            for (int rowIdx = 0; rowIdx < data.Count; rowIdx++)
            {
                var rowData = data[rowIdx];
                var row = rows[rowIdx + tableDataStartRowIndex];
                var cells = row.Elements<TableCell>().ToList();

                // 确保有足够的列
                while (cells.Count < rowData.Count)
                {
                    row.AppendChild(new TableCell(new Paragraph(new Run(new Text()))));
                    cells = row.Elements<TableCell>().ToList();
                }

                // 填充单元格
                for (int colIdx = 0; colIdx < rowData.Count; colIdx++)
                {
                    var cell = cells[colIdx] ?? new TableCell();
                    string cellValue = rowData[colIdx];

                    // 清除现有内容
                    var paragraphs = cell.Elements<Paragraph>().ToList();
                    if (paragraphs.Count > 0)
                    {
                        var firstPara = paragraphs[0];
                        firstPara.RemoveAllChildren<Run>();

                        // 保留原有格式
                        Run? originalRun = cell.Descendants<Run>().FirstOrDefault();
                        RunProperties? properties = originalRun?.RunProperties?.CloneNode(true) as RunProperties;

                        var newRun = new Run();
                        if (properties != null)
                        {
                            newRun.RunProperties = properties;
                        }
                        newRun.AppendChild(new Text(cellValue));

                        firstPara.AppendChild(newRun);

                        // 删除额外段落
                        for (int i = 1; i < paragraphs.Count; i++)
                        {
                            paragraphs[i].Remove();
                        }
                    }
                    else
                    {
                        // 创建新段落
                        cell.AppendChild(new Paragraph(new Run(new Text(cellValue))));
                    }
                }
            }

            //使用默认配置格式化表格
            if (useDefaultFormat)
            {
                FormatWordTable(table);
            }
        }

        /// <summary>
        /// 动态创建带表格的Word文档
        /// </summary>
        /// <param name="tablesData">表格数据字典（表格索引或标识符 -> 行数据）</param>
        /// <returns></returns>
        public static Stream CreateDocumentWithTables(List<List<List<string>>> tablesData)
        {
            var stream = new MemoryStream();

            using (WordprocessingDocument doc = WordprocessingDocument.Create(stream, DocumentFormat.OpenXml.WordprocessingDocumentType.Document))
            {
                // 创建主文档部分
                MainDocumentPart mainPart = doc.AddMainDocumentPart();
                mainPart.Document = new Document();
                Body body = mainPart.Document.AppendChild(new Body());

                // 为每个表格创建标题和表格
                foreach (var tableData in tablesData)
                {
                    // 添加表格标题
                    var titlePara = new Paragraph();
                    var titleRun = new Run();
                    titleRun.AppendChild(new Text($"表格 {tablesData.IndexOf(tableData) + 1}"));
                    titlePara.AppendChild(titleRun);
                    body.AppendChild(titlePara);

                    // 创建表格
                    Table table = CreateTableWithData(tableData);
                    body.AppendChild(table);

                    // 添加分页符
                    if (tablesData.IndexOf(tableData) < tablesData.Count - 1)
                    {
                        body.AppendChild(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));
                    }
                }

                mainPart.Document.Save();
            }

            stream.Position = 0;
            return stream;
        }

        /// <summary>
        /// 创建表格并填充数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Table CreateTableWithData(List<List<string>> data)
        {
            Table table = new Table();

            // 设置表格样式
            TableProperties props = new TableProperties(
                new TableBorders(
                    new TopBorder { Val = BorderValues.Single, Size = 4 },
                    new BottomBorder { Val = BorderValues.Single, Size = 4 },
                    new LeftBorder { Val = BorderValues.Single, Size = 4 },
                    new RightBorder { Val = BorderValues.Single, Size = 4 },
                    new InsideHorizontalBorder { Val = BorderValues.Single, Size = 4 },
                    new InsideVerticalBorder { Val = BorderValues.Single, Size = 4 }
                ),
                new TableJustification { Val = TableRowAlignmentValues.Center }
            );
            table.AppendChild(props);

            // 创建表格行
            foreach (var rowData in data)
            {
                TableRow row = new TableRow();

                foreach (string cellValue in rowData)
                {
                    TableCell cell = new TableCell();
                    cell.Append(new Paragraph(new Run(new Text(cellValue))));

                    // 设置单元格属性
                    TableCellProperties cellProps = new TableCellProperties(
                        new TableCellWidth { Type = TableWidthUnitValues.Auto }
                    );
                    cell.PrependChild(cellProps);

                    row.AppendChild(cell);
                }

                table.AppendChild(row);
            }

            return table;
        }

        /// <summary>
        /// 格式化表格
        /// </summary>
        /// <param name="table">目标表格</param>
        private static void FormatWordTable(Table table)
        {
            try
            {
                WordTableBordersHelper.SetTableBorders(table);
                WordTableFontHelper.SetTableFont(table);
                WordTableAlignmentHelper.SetTableAlignment(table);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

    }
}
